/**
 * VIR Circuit Physics Simulation Library - TypeScript Version
 * 
 * 🎯 坐标系统规范
 * ================
 * 
 * 1. 画布坐标系 (Canvas Coordinate System)
 *    - 最顶层的坐标参考系，原点(0,0)在画布左上角
 *    - 鼠标坐标、元件position都是相对于画布的坐标
 *    - 从工具栏拖拽创建元件时，鼠标在画布中的坐标就是元件的position
 * 
 * 2. 元件坐标系 (Component Coordinate System)  
 *    - 每个元件有自己的局部坐标系，原点在元件中心
 *    - 元件的position和rotation是相对于画布的
 *    - Pin的坐标是相对于元件中心的局部坐标
 *    - getPinPosition()返回Pin在元件局部坐标系中的位置
 * 
 * 3. 坐标转换公式
 *    - Pin世界坐标 = 元件.position + Pin局部坐标
 *    - 元件SVG: transform="translate(position.x, position.y) rotate(rotation)"
 *    - Pin SVG: <circle cx="局部坐标.x" cy="局部坐标.y" .../>
 * 
 * 4. CSS变换规则
 *    - 元件CSS变换：作用于元件整体，影响位置和旋转
 *    - Pin CSS变换：只作用于Pin自身（如hover缩放），以Pin中心为原点
 *    - transform-origin: center center 确保Pin变换以自身中心为准
 */

import { svgTemplates, renderTemplate } from './editor/svg-templates.js';
import { globalMgr } from './globalMgr.js';

/**
 * 注入连接系统所需的CSS样式
 */
export function injectConnectionStyles(): void {
  const styleId = 'connection-system-styles';
  if (document.getElementById(styleId)) return;

  const style = document.createElement('style');
  style.id = styleId;
  style.textContent = `
    @keyframes pulse {
      0% { transform: scale(1); opacity: 1; }
      50% { transform: scale(1.2); opacity: 0.8; }
      100% { transform: scale(1); opacity: 1; }
    }
    
    @keyframes slideIn {
      from { transform: translateX(100%); opacity: 0; }
      to { transform: translateX(0); opacity: 1; }
    }
    
    @keyframes slideOut {
      from { transform: translateX(0); opacity: 1; }
      to { transform: translateX(100%); opacity: 0; }
    }
    
    g [data-pin-id] {
      cursor: pointer !important;
      /* 基础样式 - 增大stroke-width来扩大hover触发区域 */
      r: 3 !important;
      fill: #FF6347 !important;
      stroke: #000000 !important;
      stroke-width: 2 !important;
      /* 只对fill属性添加过渡，避免transform问题 */
      transition: fill 0.2s ease, r 0.2s ease !important;
    }
    
    /* 基础hover效果 - 使用r属性增大而不是transform缩放 */
    g [data-pin-id]:not(.connecting):not(.valid-target):not(.invalid-target):hover {
      fill: #4CAF50 !important;
      r: 8 !important;
      transition: fill 0.2s ease, r 0.2s ease !important;
    }
    
    /* 连接状态样式 - 覆盖hover效果 */
    g [data-pin-id].connecting {
      animation: pulse 1s infinite;
      filter: brightness(1.1) drop-shadow(0 0 3px #2196F3);
      fill: #2196F3 !important;
      r: 6 !important;
      transition: none;
    }
    
    g [data-pin-id].valid-target {
      animation: pulse 0.6s infinite;
      filter: brightness(1.3) drop-shadow(0 0 4px #4CAF50);
      fill: #4CAF50 !important;
      r: 6 !important;
      transition: none;
    }
    
    g [data-pin-id].invalid-target {
      opacity: 0.6;
      filter: brightness(0.8) grayscale(0.3);
      fill: #F44336 !important;
      transition: opacity 0.2s ease, filter 0.2s ease, fill 0.2s ease;
    }
    
    #connection-line {
      pointer-events: none;
      z-index: 1000;
    }
  `;
  
  document.head.appendChild(style);
}

/**
 * 命中类型枚举，明确标识被命中对象的哪一部分
 */
export enum HitType {
  None = "none",           // 未命中
  Pin = "pin",             // 命中元件的引脚
  ComponentBody = "component-body", // 命中元件的本体（非引脚区域）
  Wire = "wire",          // 命中导线
  WireEndpoint = "wire-endpoint"   // 命中导线的端点（可能用于连接或拖动）
}

/**
 * 连接状态枚举
 */
export enum ConnectionState {
  None = 'none',           // 无连接状态
  Pending = 'pending',     // 连接进行中（已选择起始Pin）
  Connecting = 'connecting', // 正在拖拽连接线
  Complete = 'complete'    // 连接完成
}

/**
 * 连线样式枚举
 */
export enum ConnectionStyle {
  Straight = 'straight',
  Bezier = 'bezier', 
  Handdrawn = 'handdrawn'
}

/**
 * Pin样式状态
 */
export interface PinStyle {
  radius: number;
  fill: string;
  stroke: string;
  strokeWidth: number;
  opacity?: number;
  animation?: string;
}

/**
 * 连接验证结果
 */
export interface ConnectionValidationResult {
  isValid: boolean;
  reason?: string;
}

/**
 * 命中测试结果
 */
export class HitTestResult {
  constructor(
    public readonly type: HitType,
    public readonly target: IHitTestable,
    public readonly hitPoint: { x: number; y: number },
    public readonly distanceSquared: number = 0
  ) {}

  get isHit(): boolean {
    return this.type !== HitType.None;
  }

  get isPinHit(): boolean { return this.type === HitType.Pin; }
  get isComponentBodyHit(): boolean { return this.type === HitType.ComponentBody; }
  get isWireHit(): boolean { return this.type === HitType.Wire; }
}

/**
 * 定义可命中测试对象的契约
 */
export interface IHitTestable {
  /**
   * 执行命中检测
   * @param point 要测试的点，通常为世界坐标系或画布坐标系
   * @param tolerance 命中容差（像素），用于扩大点击有效区域
   * @returns 如果命中，返回包含详细信息的HitTestResult对象；否则返回null
   */
  hitTest(point: { x: number; y: number }, tolerance?: number): HitTestResult | null;
}

/**
 * 命中测试器，负责管理场景中所有可命中对象
 */
export interface IHitTester {
  register(hitTestable: IHitTestable): void;
  unregister(hitTestable: IHitTestable): void;
  hitTestAll(point: { x: number; y: number }, tolerance?: number): HitTestResult[];
  hitTestFirst(point: { x: number; y: number }, tolerance?: number): HitTestResult | null;
}

/**
 * 连接管理器接口
 */
export interface IConnectionManager {
  startConnection(pin: IPin, canvas: SVGSVGElement, getElementById: (id: string) => ICircuitElement | undefined, createWireCallback?: (sourcePin: IPin, targetPin: IPin) => void): void;
  updateConnection(x: number, y: number): void;
  completeConnection(targetPin: IPin): boolean;
  cancelConnection(): void;
  getState(): ConnectionState;
  getSourcePin(): IPin | null;
}

// Pin Interface
export interface IPin extends IHitTestable {
  id: string;  // 全局唯一标识符(GUID)
  designator: string;  // 元件数据手册上定义的引脚编号或名称
  displayName?: string;  // 可读的标签，可为空
  electricalType: 'Input' | 'Output' | 'Passive' | 'Power' | 'Ground';  // 电气类型
  direction: 'In' | 'Out' | 'InOut';  // 方向
  componentId: string;  // 对应父元件的id
  position: { x: number; y: number };  // 相对于元件符号的局部坐标
  netId?: string;  // 所属网络的id (兼容旧代码)
  connectionNetId: string | null;  // 初始为null，连接后为所属网络的id
  voltage: number;  // 电压值(保留)
  current: number;  // 电流值(保留)
  connectedPins: IPin[];  // 已连接的引脚
}

export abstract class PinBase implements IPin {
  abstract id: string;
  abstract designator: string;
  abstract componentId: string;
  abstract position: { x: number; y: number };
  abstract connectionNetId: string | null;
  abstract voltage: number;
  abstract current: number;
  abstract connectedPins: IPin[];
  abstract electricalType: 'Input' | 'Output' | 'Passive' | 'Power' | 'Ground';
  abstract direction: 'In' | 'Out' | 'InOut';
  abstract displayName?: string;

  /**
   * 执行命中检测
   * point: 鼠标在画布坐标系中的坐标
   * 来自接口：IHitTestable
   */
  hitTest(point: { x: number; y: number }, tolerance: number = 5): HitTestResult | null {
    const parent = globalMgr.getElementById(this.componentId);
    if (!parent) return null;
    
    // 获取Pin在元件局部坐标系中的位置
    const pinLocalPos = parent.getPinPosition(this);
    
    // 计算Pin在画布世界坐标系中的位置
    const pinWorldPos = {
      x: parent.position.x + pinLocalPos.x,
      y: parent.position.y + pinLocalPos.y
    };

    // 计算鼠标位置与Pin世界坐标的距离
    const dx = point.x - pinWorldPos.x;
    const dy = point.y - pinWorldPos.y;
    const distanceSquared = dx * dx + dy * dy;

    const hitRadius = tolerance;
    if (distanceSquared <= hitRadius * hitRadius) {
      return new HitTestResult(
        HitType.Pin,
        this,
        pinWorldPos,
        distanceSquared
      );
    }
    return null;
  }
}

export class Pin extends PinBase {
  id: string;
  designator: string;
  componentId: string;
  position: { x: number; y: number };
  connectionNetId: string | null;
  voltage: number;
  current: number;
  connectedPins: IPin[];
  electricalType: 'Input' | 'Output' | 'Passive' | 'Power' | 'Ground';
  direction: 'In' | 'Out' | 'InOut';
  displayName?: string;



  constructor(params: {
    id: string;
    designator: string;
    componentId: string;
    position: { x: number; y: number };
    connectionNetId?: string | null;
    voltage?: number;
    current?: number;
    connectedPins?: IPin[];
    electricalType: 'Input' | 'Output' | 'Passive' | 'Power' | 'Ground';
    direction: 'In' | 'Out' | 'InOut';
    displayName?: string;
  }) {
    super();
    this.id = params.id;
    this.designator = params.designator;
    this.componentId = params.componentId;
    this.position = params.position;
    this.connectionNetId = params.connectionNetId || null;
    this.voltage = params.voltage || 0;
    this.current = params.current || 0;
    this.connectedPins = params.connectedPins || [];
    this.electricalType = params.electricalType;
    this.direction = params.direction;
    this.displayName = params.displayName;
  }

  /**
   * Pin的独立绘制接口 - 在指定位置绘制Pin
   * 
   * @param localPosition Pin在元件局部坐标系中的位置
   * @param style 可选的样式覆盖
   * 
   * 坐标说明：
   * - localPosition: 相对于元件中心的局部坐标
   * - cx,cy: 直接使用局部坐标，因为外层g元素会处理到画布坐标的转换
   * - CSS transform: 以Pin中心为原点进行缩放等变换
   */
  getSVG(localPosition: { x: number; y: number }, style?: Partial<IStyle>): string {
    // 设置默认的r属性，让CSS有基础值可以控制
    const defaultStyle = {
      r: 3,  // 必须设置基础半径，否则CSS无法正确缩放
      fill: '#FF6347',
      stroke: '#000000',
      strokeWidth: 2  // 增大stroke-width来扩大触发区域
    };
    
    const pinStyle = { ...defaultStyle, ...style };
    
    return `<circle cx="${localPosition.x}" cy="${localPosition.y}" 
            r="${pinStyle.r}"
            fill="${pinStyle.fill}"
            stroke="${pinStyle.stroke}"
            stroke-width="${pinStyle.strokeWidth}"
            data-pin-id="${this.id}"
            data-component-id="${this.componentId}"/>`;
  }
}

// Style parameters interface
export interface IStyle {
  strokeColor: string;
  strokeWidth: number;
  fillColor: string;
  opacity: number;
  dashArray?: string;
  lineCap?: 'butt' | 'round' | 'square';
  lineJoin?: 'miter' | 'round' | 'bevel';
  cssClass?: string;
  pinStyle?: {
    visible: boolean;
    radius: number;
    fill: string;
    stroke: string;
    strokeWidth: number;
  };
}

// 原有的Drawable element interface 保持兼容
export interface IDrawable {
  getStyle(): IStyle;
  getSVG(): string;
}

// Circuit Element Interface (纯逻辑接口)
export interface ICircuitElement {
  readonly id: string;
  readonly type: string;
  position: { x: number; y: number };
  rotation: number;
  pins: IPin[];
  properties: Record<string, any>;

  calculate(): void;
  connectTo(pin: IPin, targetPin: IPin): void;
  disconnectFrom(pin: IPin): void;
  getPinByName(name: string): IPin | undefined;
  getPinPosition(pin: IPin): { x: number; y: number };
}

// Abstract Base Class implementing both interfaces
export abstract class CircuitElement implements ICircuitElement, IDrawable, IHitTestable {
  // Default style parameters
  protected defaultStyle: IStyle = {
    strokeColor: '#333333',
    strokeWidth: 2,
    fillColor: 'transparent',
    opacity: 1,
    lineCap: 'round',
    lineJoin: 'round',
    pinStyle: {
      visible: true,
      radius: 3,  // 减小半径
      fill: '#FF6347',
      stroke: '#000000',
      strokeWidth: 1
    }
  };

  getStyle(): IStyle {
    return this.defaultStyle;
  }
  readonly id: string;
  readonly type: string;
  position: { x: number; y: number };
  rotation: number;
  pins: IPin[];
  properties: Record<string, any>;
  
  constructor(params: {
    id?: string;
    type: string;
    position?: { x: number; y: number };
    rotation?: number;
    pins?: Array<Omit<IPin, 'parentElement'> & {
      designator?: string;
      netId?: string;
    }>;
    properties?: Record<string, any>;
    cssClass?: string;
  }) {
    this.id = params.id || `element_${Date.now()}`;
    this.type = params.type;
    this.position = params.position || { x: 0, y: 0 };
    this.rotation = params.rotation || 0;
    this.properties = params.properties || {};
    this.defaultStyle.cssClass = params.cssClass || '';
    
    // 安全初始化pins
    this.pins = (params.pins || []).map(pin => {
      const pinParams = {
        id: pin.id,
        designator: pin.designator || '',
        displayName: pin.displayName,
        electricalType: pin.electricalType || 'Passive',
        direction: pin.direction || 'In',
        componentId: this.id,
        position: pin.position || { x: 0, y: 0 },
        connectionNetId: pin.connectionNetId || null,
        voltage: pin.voltage || 0,
        current: pin.current || 0,
        connectedPins: pin.connectedPins || [],
        netId: pin.netId
      };
      return new Pin(pinParams);
    });
    
    // 在pins初始化后注册到全局管理器
    globalMgr.registerElement(this);
  }

  getPinByName(designator: string): IPin | undefined {
    return this.pins.find(pin => pin.designator === designator);
  }

  abstract calculate(): void;

  /**
   * 来自接口：IDrawable - 完整的元件外观绘制，包含其Pin
   * 
   * 坐标系统说明：
   * - this.position: 元件在画布坐标系中的位置
   * - this.rotation: 元件相对于画布的旋转角度
   * - getPinPosition(): 返回Pin在元件局部坐标系中的坐标
   * - 外层g元素: 应用画布坐标系的变换(位置+旋转)
   * - Pin元素: 使用元件局部坐标系的坐标
   */
  getSVG(): string {
    const style = this.getStyle();
    
    // 获取元件本体的SVG（使用元件局部坐标系）
    const bodySVG = this.getBodySVG();
    
    // 获取所有Pin的SVG - Pin使用元件局部坐标
    const pinsSVG = this.pins.map(pin => {
      const pinLocalPos = this.getPinPosition(pin);
      // Pin的cx,cy使用相对于元件中心的局部坐标
      return (pin as Pin).getSVG(pinLocalPos, style.pinStyle);
    }).join('');
    
    // 外层g元素将元件从局部坐标系转换到画布坐标系
    return `<g class="${this.defaultStyle.cssClass}" 
              transform="translate(${this.position.x}, ${this.position.y}) rotate(${this.rotation})"
              data-element-id="${this.id}">
              ${bodySVG}
              ${pinsSVG}
            </g>`;
  }

  /**
   * 获取元件本体的SVG（不包含Pin）
   * 子类应该重写此方法来定义元件的外观
   */
  protected getBodySVG(): string {
    const template = svgTemplates[this.type];
    if (!template) {
      console.warn(`No SVG template found for element type: ${this.type}`);
      return '';
    }

    const style = this.getStyle();
    const templateData = {
      ...style,
      x: 0,
      y: 0,
      rotation: 0, // 旋转由外层g元素处理
      cssClass: this.defaultStyle.cssClass,
      id: this.id,
      pins: [] // 不在模板中处理Pin
    };

    return renderTemplate(template.template, templateData);
  }


  // 拖动状态属性
  protected isDragging: boolean = false;
  protected dragStartPos: { x: number; y: number } | null = null;
  protected initialPose: any = null;

  /**
   * 处理鼠标按下事件
   */
  onMouseDown(point: { x: number; y: number }): boolean {
    // 基础实现 - 子类可重写
    this.isDragging = true;
    this.dragStartPos = point;
    return true;
  }

  /**
   * 处理拖动 - 基础实现
   * 来自接口：ICircuitElement
   */
  handleDrag(point: { x: number; y: number }): boolean {
    if (!this.isDragging || !this.dragStartPos) {
      return false;
    }
    
    const dx = point.x - this.dragStartPos.x;
    const dy = point.y - this.dragStartPos.y;
    
    // 更新元件位置
    this.position.x += dx;
    this.position.y += dy;
    
    // 更新拖动起始位置
    this.dragStartPos.x = point.x;
    this.dragStartPos.y = point.y;
    
    return true;
  }

  /**
   * 处理鼠标释放事件
   */
  onMouseUp(): boolean {
    this.isDragging = false;
    this.dragStartPos = null;
    return true;
  }

  /**
   * 计算引脚位置
   * 来自接口：ICircuitElement
   */
  getPinPosition(pin: IPin): { x: number; y: number } {
    // 基础实现，子类可重写
    switch(pin.id) {
      case 'in': return { x: -10, y: 0 };
      case 'out': return { x: 10, y: 0 };
      default: return { x: 0, y: 0 };
    }
  }

  /**
   * 连接两个引脚并合并网络
   * 来自接口：ICircuitElement
   */
  connectTo(pin: IPin, targetPin: IPin): void {
    // 基础连接
    pin.connectedPins.push(targetPin);
    targetPin.connectedPins.push(pin);

    // 网络管理
    if (!pin.netId && !targetPin.netId) {
      // 两个引脚都未分配网络，创建新网络
      const netId = globalMgr.createNet(pin);
      targetPin.netId = netId;
      globalMgr.getNetPins(netId).push(targetPin);
    } else if (pin.netId && !targetPin.netId) {
      // 目标引脚加入源引脚的网络
      targetPin.netId = pin.netId;
      globalMgr.getNetPins(pin.netId).push(targetPin);
    } else if (!pin.netId && targetPin.netId) {
      // 源引脚加入目标引脚的网络
      pin.netId = targetPin.netId;
      globalMgr.getNetPins(targetPin.netId).push(pin);
    } else if (pin.netId !== targetPin.netId) {
      // 合并两个不同的网络
      globalMgr.mergeNets(pin.netId!, targetPin.netId!);
    }
  }

  disconnectFrom(pin: IPin): void {
    // Implementation for disconnecting pins
    pin.connectedPins = pin.connectedPins.filter(p => p !== pin);
  }

  /**
   * 执行命中检测
   * 来自接口：IHitTestable
   */
  hitTest(point: { x: number; y: number }, tolerance: number = 5): HitTestResult | null {
    // 优先检测更精细的部分：引脚
    for (const pin of this.pins) {
      const pinResult = pin.hitTest(point, tolerance);
      if (pinResult && pinResult.isHit) {
        return pinResult; // 如果命中任何引脚，立即返回，不再检查元件本体
      }
    }

    // 如果没有命中任何引脚，检查元件本体
    const svgElement = document.querySelector(`g[data-element-id="${this.id}"]`);
    if (svgElement) {
      const bbox = svgElement.getBoundingClientRect();
      const svg = svgElement.closest('svg');
      if (svg) {
        const pt = svg.createSVGPoint();
        pt.x = bbox.left;
        pt.y = bbox.top;
        const ctm = svg.getScreenCTM();
        if (ctm) {
          const svgP = pt.matrixTransform(ctm.inverse());
          
          // 计算点击点与元件边界的距离
          const dx = point.x - (this.position.x + svgP.x);
          const dy = point.y - (this.position.y + svgP.y);
          const distanceSquared = dx * dx + dy * dy;

          // 如果点击点在元件边界内
          if (Math.abs(dx) <= bbox.width/2 + tolerance && 
              Math.abs(dy) <= bbox.height/2 + tolerance) {
            return new HitTestResult(
              HitType.ComponentBody,
              this,
              { x: this.position.x, y: this.position.y },
              distanceSquared
            );
          }
        }
      }
    }

    return null;
  }
}

// ================== Basic Circuit Elements ================== //

export class Resistor extends CircuitElement {
  constructor(params: {
    id?: string;
    position?: { x: number; y: number };
    rotation?: number;
    resistance?: number;
    tolerance?: number;
  }) {
    const elementId = params.id || `element_${Date.now()}`;
    super({
      ...params,
      type: 'resistor',
      pins: [
        new Pin({
          id: 'in',
          designator: '1',
          displayName: 'Positive',
          electricalType: 'Passive',
          direction: 'In',
          componentId: elementId,
          position: { x: -30, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        }),
        new Pin({
          id: 'out',
          designator: '2',
          displayName: 'Negative',
          electricalType: 'Passive',
          direction: 'Out',
          componentId: elementId,
          position: { x: 30, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        })
      ],
      properties: {
        resistance: params.resistance || 1000, // ohms
        tolerance: params.tolerance || 5 // %
      },
      cssClass: 'circuit-resistor'
    });
    // Override default style for resistor
    this.defaultStyle = {
      ...this.defaultStyle,
      strokeColor: '#8B4513', // Brown color for resistor
      strokeWidth: 3
    };
  }

  calculate(): void {
    // Ohm's Law: V = I * R
    const inputPin = this.getPinByName('in');
    const outputPin = this.getPinByName('out');
    if (inputPin && outputPin) {
      const voltageDrop = inputPin.current * this.properties.resistance;
      outputPin.voltage = inputPin.voltage - voltageDrop;
      outputPin.current = inputPin.current;
    }
  }

  // 实现IDrawable接口的getSVG方法
  /**
   * 获取电阻色环颜色
   * 来自接口：IDrawable
   */
  private getColorBands(): {color: string; value: number}[] {
    const resistance = this.properties.resistance;
    const tolerance = this.properties.tolerance || 5;
    const digits = resistance.toString().replace('.','').split('').map(Number);
    
    // 标准色环颜色编码
    const colorMap = [
      {color: 'black', value: 0},
      {color: 'brown', value: 1},
      {color: 'red', value: 2},
      {color: 'orange', value: 3},
      {color: 'yellow', value: 4},
      {color: 'green', value: 5},
      {color: 'blue', value: 6},
      {color: 'violet', value: 7},
      {color: 'gray', value: 8},
      {color: 'white', value: 9},
      {color: 'gold', value: -1}, // 乘数0.1
      {color: 'silver', value: -2} // 乘数0.01
    ];
    
    // 计算色环
    const bands = [];
    if (resistance < 10) {
      bands.push(colorMap[digits[0]]); // 第一位有效数字
      bands.push(colorMap[0]); // 第二位为0
      bands.push(colorMap[digits.length-1]); // 乘数
    } else {
      bands.push(colorMap[digits[0]]); // 第一位有效数字
      if (digits.length > 1) bands.push(colorMap[digits[1]]); // 第二位有效数字
      bands.push(colorMap[digits.length-1]); // 乘数
    }
    
    // 容差环
    bands.push(tolerance === 5 ? colorMap[1] : 
              tolerance === 10 ? colorMap[2] : 
              {color: 'gold', value: tolerance});
    
    return bands;
  }

  /**
   * 来自接口：IDrawable
   * 电阻使用基类的标准getSVG实现，只需要重写getBodySVG来定义本体外观
   */
  protected getBodySVG(): string {
    const bands = this.getColorBands();
    const style = this.getStyle();
    
    // 生成色环SVG
    const bandWidth = 4;
    const bandSpacing = 2;
    let bandSvg = '';
    bands.forEach((band, i) => {
      const x = -20 + (i * (bandWidth + bandSpacing));
      bandSvg += `<rect x="${x}" y="-6" width="${bandWidth}" height="12" 
                fill="${band.color}" stroke="none"/>`;
    });

    // 基础电阻SVG（使用元件局部坐标系，中心在原点）
    const baseSvg = `<rect x="-25" y="-8" width="50" height="16" 
                    fill="beige" stroke="${style.strokeColor}" 
                    stroke-width="${style.strokeWidth}"/>`;
    
    return `${baseSvg}${bandSvg}`;
  }

  /**
   * 计算引脚位置
   * 来自接口：ICircuitElement
   */
  getPinPosition(pin: IPin): { x: number; y: number } {
    // 电阻特有引脚位置
    switch(pin.id) {
      case 'in': return { x: -30, y: 0 };
      case 'out': return { x: 30, y: 0 };
      default: return { x: 0, y: 0 };
    }
  }
}

export class Capacitor extends CircuitElement {
  constructor(params: {
    id?: string;
    position?: { x: number; y: number };
    rotation?: number;
    capacitance?: number;
    voltageRating?: number;
  }) {
    const elementId = params.id || `element_${Date.now()}`;
    super({
      ...params,
      type: 'capacitor',
      pins: [
        new Pin({
          id: 'in',
          designator: '1',
          displayName: 'Positive',
          electricalType: 'Passive',
          direction: 'In',
          componentId: elementId,
          position: { x: -30, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        }),
        new Pin({
          id: 'out',
          designator: '2',
          displayName: 'Negative',
          electricalType: 'Passive',
          direction: 'Out',
          componentId: elementId,
          position: { x: 30, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        })
      ],
      properties: {
        capacitance: params.capacitance || 1e-6, // Farads
        voltageRating: params.voltageRating || 50 // Volts
      },
      cssClass: 'circuit-capacitor'
    });
    // Override default style for capacitor
    this.defaultStyle = {
      ...this.defaultStyle,
      strokeColor: '#1E90FF', // DodgerBlue color for capacitor
      dashArray: '5,3' // Dashed line style
    };
  }

  calculate(): void {
    // Capacitor equation: I = C * dV/dt
    // Simplified implementation for demo
    const inputPin = this.getPinByName('in');
    const outputPin = this.getPinByName('out');
    if (inputPin && outputPin) {
      outputPin.voltage = inputPin.voltage;
      outputPin.current = inputPin.current;
    }
  }

  /**
   * 电容使用完整的SVG实现，完全覆盖基类行为
   * 来自接口：IDrawable
   */
  getSVG(): string {
    const style = this.getStyle();
    
    // 电容本体SVG - 优化性能版本
    const plateHeight = 24;  // 平行板高度
    const plateX = 6;         // 板的位置（稍微调大间距）
    
    // 获取所有Pin的SVG - Pin使用元件局部坐标
    const pinsSVG = this.pins.map(pin => {
      const pinLocalPos = this.getPinPosition(pin);
      return (pin as Pin).getSVG(pinLocalPos, style.pinStyle);
    }).join('');
    
    // 调试模式：显示可点击区域边框
    const debugOutline = `
      <rect x="-30" y="-15" width="60" height="30" 
            fill="rgba(255,0,0,0.1)" 
            stroke="red" 
            stroke-width="1" 
            stroke-dasharray="3,3"
            opacity="0.5"
            class="debug-hit-area"/>
    `;
    
    // 完整的电容SVG（包含本体和引脚）
    return `<g class="${this.defaultStyle.cssClass}" 
              transform="translate(${this.position.x}, ${this.position.y}) rotate(${this.rotation})"
              data-element-id="${this.id}"
              style="cursor: move">
              <path d="M ${-plateX} ${-plateHeight/2} L ${-plateX} ${plateHeight/2} 
                       M ${plateX} ${-plateHeight/2} L ${plateX} ${plateHeight/2}
                       M ${-plateX} 0 L -30 0
                       M ${plateX} 0 L 30 0"
                stroke="${style.strokeColor}" 
                stroke-width="${style.strokeWidth}"
                stroke-dasharray="${style.dashArray || 'none'}"
                fill="none"
                stroke-linecap="round"/>
              ${debugOutline}
              ${pinsSVG}
            </g>`;
  }



  /**
   * 自定义电容的hitTest方法，增大鼠标捕获区域
   * 来自接口：IHitTestable
   */
  hitTest(point: { x: number; y: number }, tolerance: number = 15): HitTestResult | null {
    // 优先检测引脚
    for (const pin of this.pins) {
      const pinResult = pin.hitTest(point, tolerance);
      if (pinResult && pinResult.isHit) {
        return pinResult;
      }
    }

    // 电容特有的大范围hit区域 - 包括平行板和板间空白区域
    const extendedWidth = 60; // 大幅扩大水平捕获范围（覆盖整个电容宽度）
    const extendedHeight = 30; // 扩大垂直捕获范围

    // 转换点到元件局部坐标系
    const localPoint = {
      x: point.x - this.position.x,
      y: point.y - this.position.y
    };

    // 检查是否在扩展的矩形区域内（包括板间空白区域）
    // 在局部坐标系中，元件中心是原点(0,0)，所以需要检查是否在[-extendedWidth/2, extendedWidth/2]范围内
    if (localPoint.x >= -extendedWidth/2 - tolerance && 
        localPoint.x <= extendedWidth/2 + tolerance &&
        localPoint.y >= -extendedHeight/2 - tolerance && 
        localPoint.y <= extendedHeight/2 + tolerance) {
      return new HitTestResult(
        HitType.ComponentBody,
        this,
        { x: this.position.x, y: this.position.y },
        localPoint.x * localPoint.x + localPoint.y * localPoint.y
      );
    }

    return null;
  }

  /**
   * 计算引脚位置
   * 来自接口：ICircuitElement
   */
  getPinPosition(pin: IPin): { x: number; y: number } {
    // 电容特有引脚位置（移动到平行板外侧）
    switch(pin.id) {
      case 'in': return { x: -30, y: 0 };  // 向左移动
      case 'out': return { x: 30, y: 0 };   // 向右移动
      default: return { x: 0, y: 0 };
    }
  }
}

export class Inductor extends CircuitElement {
  constructor(params: {
    id?: string;
    position?: { x: number; y: number };
    rotation?: number;
    inductance?: number;
    currentRating?: number;
  }) {
    const elementId = params.id || `element_${Date.now()}`;
    super({
      ...params,
      type: 'inductor',
      pins: [
        new Pin({
          id: 'in',
          designator: '1',
          displayName: 'Positive',
          electricalType: 'Passive',
          direction: 'In',
          componentId: elementId,
          position: { x: -25, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        }),
        new Pin({
          id: 'out',
          designator: '2',
          displayName: 'Negative',
          electricalType: 'Passive',
          direction: 'Out',
          componentId: elementId,
          position: { x: 25, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        })
      ],
      properties: {
        inductance: params.inductance || 1e-3, // Henries
        currentRating: params.currentRating || 1 // Amps
      },
      cssClass: 'circuit-inductor'
    });
    // Override default style for inductor
    this.defaultStyle = {
      ...this.defaultStyle,
      strokeColor: '#9370DB', // MediumPurple color for inductor
      strokeWidth: 2.5
    };
  }

  calculate(): void {
    // Inductor equation: V = L * dI/dt
    // Simplified implementation for demo
    const inputPin = this.getPinByName('in');
    const outputPin = this.getPinByName('out');
    if (inputPin && outputPin) {
      outputPin.voltage = inputPin.voltage;
      outputPin.current = inputPin.current;
    }
  }



  /**
   * 计算引脚位置
   * 来自接口：ICircuitElement
   */
  getPinPosition(pin: IPin): { x: number; y: number } {
    // 电压源特有引脚位置（引线终端）
    switch(pin.id) {
      case 'in': return { x: -25, y: 0 };  // 向左延长引线
      case 'out': return { x: 25, y: 0 };   // 向右延长引线
      default: return { x: 0, y: 0 };
    }
  }
}

export class VoltageSource extends CircuitElement {
  constructor(params: {
    id?: string;
    position?: { x: number; y: number };
    rotation?: number;
    voltage?: number;
    internalResistance?: number;
  }) {
    const elementId = params.id || `element_${Date.now()}`;
    super({
      ...params,
      type: 'voltage_source',
      pins: [
        new Pin({
          id: 'in',
          designator: '1',
          displayName: 'Negative',
          electricalType: 'Power',
          direction: 'In',
          componentId: elementId,
          position: { x: -25, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        }),
        new Pin({
          id: 'out',
          designator: '2',
          displayName: 'Positive',
          electricalType: 'Power',
          direction: 'Out',
          componentId: elementId,
          position: { x: 25, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        })
      ],
      properties: {
        voltage: params.voltage || 5, // Volts
        internalResistance: params.internalResistance || 0.1 // Ohms
      },
      cssClass: 'circuit-voltage-source'
    });
    // Override default style for voltage source
    this.defaultStyle = {
      ...this.defaultStyle,
      strokeColor: '#FF4500', // OrangeRed color for voltage source
      fillColor: '#FFFACD' // LemonChiffon fill
    };
  }

  calculate(): void {
    const outputPin = this.getPinByName('out');
    const inputPin = this.getPinByName('in');
    if (outputPin && inputPin) {
      outputPin.voltage = this.properties.voltage;
      outputPin.current = inputPin.current;
    }
  }

  /**
   * 电压源使用基类的标准getSVG实现，只需要重写getBodySVG来定义本体外观
   */
  protected getBodySVG(): string {
    const style = this.getStyle();
    
    // 电压源本体SVG - 圆圈内部有+和-符号（使用元件局部坐标系，中心在原点）
    const radius = 20;
    
    return `<circle cx="0" cy="0" r="${radius}" 
                    fill="${style.fillColor}" 
                    stroke="${style.strokeColor}" 
                    stroke-width="${style.strokeWidth}"/>
            <text x="-8" y="-5" font-family="Arial" font-size="14" font-weight="bold" fill="${style.strokeColor}">+</text>
            <text x="-8" y="10" font-family="Arial" font-size="14" font-weight="bold" fill="${style.strokeColor}">−</text>`;
  }



  /**
   * 计算引脚位置
   * 来自接口：ICircuitElement
   */
  getPinPosition(pin: IPin): { x: number; y: number } {
    // 电压源特有引脚位置（引线终端）
    switch(pin.id) {
      case 'in': return { x: -25, y: 0 };  // 向左延长引线
      case 'out': return { x: 25, y: 0 };   // 向右延长引线
      default: return { x: 0, y: 0 };
    }
  }
}

export class CurrentSource extends CircuitElement {
  constructor(params: {
    id?: string;
    position?: { x: number; y: number };
    rotation?: number;
    current?: number;
    internalResistance?: number;
  }) {
    const elementId = params.id || `element_${Date.now()}`;
    super({
      ...params,
      type: 'current_source',
      pins: [
        new Pin({
          id: 'in',
          designator: '1',
          displayName: 'Negative',
          electricalType: 'Power',
          direction: 'In',
          componentId: elementId,
          position: { x: -25, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        }),
        new Pin({
          id: 'out',
          designator: '2',
          displayName: 'Positive',
          electricalType: 'Power',
          direction: 'Out',
          componentId: elementId,
          position: { x: 25, y: 0 },
          connectionNetId: null,
          voltage: 0,
          current: 0,
          connectedPins: []
        })
      ],
      properties: {
        current: params.current || 0.1, // Amps
        internalResistance: params.internalResistance || 1000 // Ohms
      },
      cssClass: 'circuit-current-source'
    });
    // Override default style for current source
    this.defaultStyle = {
      ...this.defaultStyle,
      strokeColor: '#32CD32', // LimeGreen color for current source
      fillColor: '#F0FFF0' // Honeydew fill
    };
  }

  calculate(): void {
    const outputPin = this.getPinByName('out');
    const inputPin = this.getPinByName('in');
    if (outputPin && inputPin) {
      outputPin.current = this.properties.current;
      outputPin.voltage = inputPin.voltage;
    }
  }

  /**
   * 电流源使用基类的标准getSVG实现，只需要重写getBodySVG来定义本体外观
   */
  protected getBodySVG(): string {
    const style = this.getStyle();
    
    // 电流源本体SVG - 圆圈内部有箭头（使用元件局部坐标系，中心在原点）
    const radius = 20;
    
    return `<circle cx="0" cy="0" r="${radius}" 
                    fill="${style.fillColor}" 
                    stroke="${style.strokeColor}" 
                    stroke-width="${style.strokeWidth}"/>
            <path d="M -10,-8 L 10,0 L -10,8 Z" 
                   fill="${style.strokeColor}" 
                   stroke="none"/>`;
  }



  /**
   * 计算引脚位置
   * 来自接口：ICircuitElement
   */
  getPinPosition(pin: IPin): { x: number; y: number } {
    // 电流源特有引脚位置（与电压源一致）
    switch(pin.id) {
      case 'in': return { x: -25, y: 0 };  // 向左延长引线
      case 'out': return { x: 25, y: 0 };   // 向右延长引线
      default: return { x: 0, y: 0 };
    }
  }
}

// ================== Wire Interface and Implementation ================== //

/**
 * Wire连接接口定义
 * Wire作为独立的连接组件，不继承CircuitElement，只负责连接两个元件的Pin
 * 重构为被动模式：元件拖动时不设置wire姿态，wire自行获取两端pin位置进行渲染
 */
export interface IWire {
  /** 唯一标识符 */
  readonly id: string;
  /** 类型标识，固定为'wire' */
  readonly type: 'wire';
  /** 起始连接的Pin ID */
  readonly startPinId: string;
  /** 结束连接的Pin ID */
  readonly endPinId: string;
  /** 连线样式 */
  style: ConnectionStyle;
  /** Wire属性（如电阻等） */
  readonly properties: Record<string, any>;
  /** 连线宽度 */
  strokeWidth: number;
  /** 连线颜色 */
  strokeColor: string;
  
  /** 渲染方法：根据Pin的实际位置动态绘制连线 */
  render(getPinWorldPosition: (pinId: string) => { x: number; y: number } | null): string;
  
  /** 获取连接的Pin信息 */
  getConnectedPins(): { startPin: IPin | null; endPin: IPin | null };
  
  /** 检查连接有效性 */
  isValid(): boolean;
  
  /** 命中检测 */
  hitTest(point: { x: number; y: number }, tolerance?: number): HitTestResult | null;
  
  /** 
   * 通知wire重新渲染（被动模式）
   * 当连接的元件位置变化时调用，wire自行获取pin位置进行计算
   */
  requestRender(): void;
}

/**
 * Wire实现类 - 纯连接组件
 * 不包含Pin，只负责连接两个元件的Pin
 * 重构为被动模式：元件拖动时不设置wire姿态，wire自行获取两端pin位置进行渲染
 */
export class Wire implements IWire, IHitTestable {
  public readonly type: 'wire' = 'wire';
  
  // IWire接口属性
  public readonly id: string;
  public readonly startPinId: string;
  public readonly endPinId: string;
  public style: ConnectionStyle;
  public strokeWidth: number = 3;
  public strokeColor: string = '#333333';
  public readonly properties: Record<string, any> = { resistance: 0.01 };
  
  // 渲染状态管理
  private needsRender: boolean = true;
  private lastRenderedSvg: string = '';
  
  // Wire特有拖动状态（用于独立Wire拖动）- 仅用于未连接的wire
  private wireDragMode: 'none' | 'whole' | 'start' | 'end' = 'none';
  private initialWirePose: any = null;
  private isDragging: boolean = false;
  private dragStartPos: { x: number; y: number } | null = null;
  
  // Wire特有姿态数据（仅用于独立Wire，未连接pin时）
  private wirePose: any = {
    position: { x: 0, y: 0 },
    rotation: 0,
    startPoint: { x: 0, y: 0 },
    endPoint: { x: 0, y: 0 },
    style: ConnectionStyle.Straight
  };
  
  constructor(params: {
    id?: string;
    startPinId?: string;
    endPinId?: string;
    position?: { x: number; y: number };
    rotation?: number;
    length?: number;
    resistance?: number;
    startPoint?: { x: number; y: number };
    endPoint?: { x: number; y: number };
    style?: ConnectionStyle;
    strokeWidth?: number;
    strokeColor?: string;
  }) {
    const wireId = params.id || `wire_${Date.now()}`;
    const resistance = params.resistance || 0.01;
    
    // 初始化IWire属性
    this.id = wireId;
    this.startPinId = '';
    this.endPinId = '';
    this.style = params.style || ConnectionStyle.Straight;
    this.strokeWidth = params.strokeWidth || 3;
    this.strokeColor = params.strokeColor || '#333333';
    this.properties = { resistance };
    
    // 如果提供了startPinId/endPinId，使用新架构（连接Pin）
    if (params.startPinId && params.endPinId) {
      // 新架构Wire：连接两个已存在的Pin
      this.startPinId = params.startPinId;
      this.endPinId = params.endPinId;
      this.style = params.style || ConnectionStyle.Straight;
      // 自动注册到GlobalManager
      globalMgr.registerWire(this);
    } else {
      // 独立Wire：直接通过坐标创建
      const startPos = params.startPoint || { x: -25, y: 0 };
      const endPos = params.endPoint || { x: 25, y: 0 };
      
      // 设置虚拟Pin ID（用于内部管理）
      this.startPinId = `${wireId}:start`;
      this.endPinId = `${wireId}:end`;
      
      // 初始化Wire姿态数据（仅用于拖动）
      const midX = (startPos.x + endPos.x) / 2;
      const midY = (startPos.y + endPos.y) / 2;
      const angle = Math.atan2(endPos.y - startPos.y, endPos.x - startPos.x) * (180 / Math.PI);
      
      this.wirePose = {
        position: { x: midX, y: midY },
        rotation: angle,
        startPoint: startPos,
        endPoint: endPos,
        style: this.style
      };
      
      // 自动注册到GlobalManager
      globalMgr.registerWire(this);
    }
  }

  

  
  // 废弃的setPose和getWirePose方法已移除，使用新的被动渲染模式
  
  /**
   * 通知wire重新渲染（被动模式）
   * 当连接的元件位置变化时调用，wire自行获取pin位置进行计算
   */
  public requestRender(): void {
    this.needsRender = true;
  }
  
  /**
   * 渲染Wire - 动态查询Pin位置并绘制连线（被动模式）
   * wire自行获取连接的pin位置进行计算，不依赖外部设置的姿态
   */
  public render(getPinWorldPosition?: (pinId: string) => { x: number; y: number } | null): string {
    // 如果不需要重新渲染且已有缓存，直接返回缓存的SVG
    if (!this.needsRender && this.lastRenderedSvg) {
      return this.lastRenderedSvg;
    }
    
    let startPos: { x: number; y: number };
    let endPos: { x: number; y: number };
    
    // 检查是否为独立Wire（未连接pin的虚拟wire）
    const isIndependentWire = this.startPinId.includes(':') && this.endPinId.includes(':');
    
    if (isIndependentWire) {
      // 独立Wire：使用内部姿态数据
      startPos = this.wirePose.startPoint;
      endPos = this.wirePose.endPoint;
    } else if (getPinWorldPosition) {
      // 连接Pin的Wire：动态查询Pin位置（被动模式核心）
      const start = getPinWorldPosition(this.startPinId);
      const end = getPinWorldPosition(this.endPinId);
      
      if (!start || !end) {
        console.warn(`Wire ${this.id}: Cannot find positions for pins ${this.startPinId} and ${this.endPinId}`);
        return this.lastRenderedSvg || '';
      }
      
      startPos = start;
      endPos = end;
      
      // 更新内部姿态数据用于命中检测等操作
      const midX = (startPos.x + endPos.x) / 2;
      const midY = (startPos.y + endPos.y) / 2;
      const angle = Math.atan2(endPos.y - startPos.y, endPos.x - startPos.x) * (180 / Math.PI);
      
      this.wirePose = {
        position: { x: midX, y: midY },
        rotation: angle,
        startPoint: startPos,
        endPoint: endPos,
        style: this.style
      };
    } else {
      console.warn(`Wire ${this.id}: No pin position function provided`);
      return this.lastRenderedSvg || '';
    }
    
    // 转换为相对于连线中点的局部坐标
    const midX = (startPos.x + endPos.x) / 2;
    const midY = (startPos.y + endPos.y) / 2;
    
    const localStart = {
      x: startPos.x - midX,
      y: startPos.y - midY
    };
    
    const localEnd = {
      x: endPos.x - midX,
      y: endPos.y - midY
    };
    
    // 根据样式渲染不同类型的连线
    let pathData: string;
    switch (this.style) {
      case ConnectionStyle.Bezier:
        pathData = this.generateBezierPath(localStart, localEnd);
        break;
      case ConnectionStyle.Handdrawn:
        pathData = this.generateHanddrawnPath(localStart, localEnd);
        break;
      default:
        pathData = this.generateStraightPath(localStart, localEnd);
        break;
    }
    
    const pathElement = this.style === ConnectionStyle.Handdrawn 
      ? `<path d="${pathData}" stroke="${this.strokeColor}" stroke-width="${this.strokeWidth}" stroke-linecap="round" stroke-linejoin="round" fill="none" pointer-events="stroke"/>`
      : `<path d="${pathData}" stroke="${this.strokeColor}" stroke-width="${this.strokeWidth}" stroke-linecap="round" fill="none" pointer-events="stroke"/>`;
    
    const svg = `<g class="wire-connection" data-wire-id="${this.id}" transform="translate(${midX}, ${midY})">
              ${pathElement}
            </g>`;
    
    // 缓存渲染结果并标记为已渲染
    this.lastRenderedSvg = svg;
    this.needsRender = false;
    
    return svg;
  }
  
  /**
   * 获取连接的Pin信息
   */
  getConnectedPins(): { startPin: IPin | null; endPin: IPin | null } {
    const startPin = globalMgr.getPinById(this.startPinId) ?? null;
    const endPin = globalMgr.getPinById(this.endPinId) ?? null;
    
    return { startPin, endPin };
  }
  
  /**
   * 检查连接有效性
   */
  isValid(): boolean {
    const { startPin, endPin } = this.getConnectedPins();
    
    // 检查两个Pin是否存在
    if (!startPin || !endPin) {
      return false;
    }
    
    // 检查是否连接到同一个元件
    if (startPin.componentId === endPin.componentId) {
      return false;
    }
    
    // 检查电气类型兼容性
    return this.isElectricalTypeCompatible(startPin, endPin);
  }
  
  /**
   * 命中检测
   * IHitTestable接口实现
   */
  hitTest(point: { x: number; y: number }, tolerance: number = 10): HitTestResult | null {
    const getPinWorldPosition = (pinId: string) => {
      const pin = globalMgr.getPinById(pinId);
      if (!pin) return null;
      
      const element = globalMgr.getElementById(pin.componentId);
      if (!element) return null;
      
      const pinLocalPos = element.getPinPosition(pin);
      return {
        x: element.position.x + pinLocalPos.x,
        y: element.position.y + pinLocalPos.y
      };
    };
    
    return this.hitTestWithPinPositions(point, getPinWorldPosition, tolerance);
  }
  
  /**
   * 使用Pin位置函数进行命中检测
   */
  hitTestWithPinPositions(point: { x: number; y: number }, getPinWorldPosition: (pinId: string) => { x: number; y: number } | null, tolerance: number = 10): HitTestResult | null {
    const startPos = getPinWorldPosition(this.startPinId);
    const endPos = getPinWorldPosition(this.endPinId);
    
    if (!startPos || !endPos) {
      return null;
    }
    
    // 计算点到线段的距离
    const distance = this.pointToLineDistance(point, startPos, endPos);
    
    if (distance <= tolerance) {
      return new HitTestResult(
        HitType.Wire,
        this,
        { x: (startPos.x + endPos.x) / 2, y: (startPos.y + endPos.y) / 2 },
        distance * distance
      );
    }
    
    return null;
  }
  
  // 私有辅助方法
  
  private generateStraightPath(start: { x: number; y: number }, end: { x: number; y: number }): string {
    return `M ${start.x} ${start.y} L ${end.x} ${end.y}`;
  }
  
  private generateBezierPath(start: { x: number; y: number }, end: { x: number; y: number }): string {
    const distance = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2));
    const curvature = Math.min(distance * 0.3, 50);
    
    const midX = (start.x + end.x) / 2;
    const midY = (start.y + end.y) / 2;
    
    const angle = Math.atan2(end.y - start.y, end.x - start.x) + Math.PI / 2;
    const controlX = midX + Math.cos(angle) * curvature;
    const controlY = midY + Math.sin(angle) * curvature;
    
    return `M ${start.x} ${start.y} Q ${controlX} ${controlY} ${end.x} ${end.y}`;
  }
  
  private generateHanddrawnPath(start: { x: number; y: number }, end: { x: number; y: number }): string {
    const distance = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2));
    const segments = Math.max(3, Math.floor(distance / 20));
    
    let pathData = `M ${start.x} ${start.y}`;
    
    for (let i = 1; i <= segments; i++) {
      const t = i / segments;
      const baseX = start.x + (end.x - start.x) * t;
      const baseY = start.y + (end.y - start.y) * t;
      
      const offsetX = (Math.random() - 0.5) * 3;
      const offsetY = (Math.random() - 0.5) * 3;
      
      const pointX = baseX + offsetX;
      const pointY = baseY + offsetY;
      
      if (i === 1) {
        pathData += ` L ${pointX} ${pointY}`;
      } else {
        const prevT = (i - 1) / segments;
        const prevX = start.x + (end.x - start.x) * prevT;
        const prevY = start.y + (end.y - start.y) * prevT;
        
        const controlX = (prevX + pointX) / 2;
        const controlY = (prevY + pointY) / 2;
        
        pathData += ` Q ${controlX} ${controlY} ${pointX} ${pointY}`;
      }
    }
    
    return pathData;
  }
  
  private pointToLineDistance(
    point: { x: number; y: number }, 
    lineStart: { x: number; y: number }, 
    lineEnd: { x: number; y: number }
  ): number {
    const A = point.x - lineStart.x;
    const B = point.y - lineStart.y;
    const C = lineEnd.x - lineStart.x;
    const D = lineEnd.y - lineStart.y;

    const dot = A * C + B * D;
    const lenSq = C * C + D * D;
    let param = -1;

    if (lenSq !== 0) {
      param = dot / lenSq;
    }

    let xx, yy;

    if (param < 0) {
      xx = lineStart.x;
      yy = lineStart.y;
    } else if (param > 1) {
      xx = lineEnd.x;
      yy = lineEnd.y;
    } else {
      xx = lineStart.x + param * C;
      yy = lineStart.y + param * D;
    }

    const dx = point.x - xx;
    const dy = point.y - yy;

    return Math.sqrt(dx * dx + dy * dy);
  }
  
  private isElectricalTypeCompatible(pin1: IPin, pin2: IPin): boolean {
    // 电气类型兼容性规则
    const incompatiblePairs: Array<[string, string]> = [
      ['Power', 'Power'],
      ['Ground', 'Ground']
    ];
    
    return !incompatiblePairs.some(([type1, type2]) => 
      (pin1.electricalType === type1 && pin2.electricalType === type2) ||
      (pin1.electricalType === type2 && pin2.electricalType === type1)
    );
  }
  
  // 废弃的Wire拖动处理方法已移除，请使用新的被动渲染模式
  public handleDrag(position: { x: number; y: number }): boolean {
    if (!this.isDragging) {
      return false;
    }
    
    if (this.wireDragMode === 'none') {
      return false;
    }
    
    if (this.wireDragMode === 'whole') {
      // 整条拖动
      const dx = position.x - this.dragStartPos!.x;
      const dy = position.y - this.dragStartPos!.y;
      
      // 更新姿态数据
      this.wirePose.startPoint.x += dx;
      this.wirePose.startPoint.y += dy;
      this.wirePose.endPoint.x += dx;
      this.wirePose.endPoint.y += dy;
      this.wirePose.position.x += dx;
      this.wirePose.position.y += dy;
      
      // 更新Wire姿态数据
      this.wirePose.position.x += dx;
      this.wirePose.position.y += dy;
      
      this.dragStartPos = { ...position };
    } else if (this.wireDragMode === 'start' || this.wireDragMode === 'end') {
      // 端点拖动
      if (this.wireDragMode === 'start') {
        this.wirePose.startPoint = { ...position };
      } else {
        this.wirePose.endPoint = { ...position };
      }
      
      // 重新计算中点和角度
      const midX = (this.wirePose.startPoint.x + this.wirePose.endPoint.x) / 2;
      const midY = (this.wirePose.startPoint.y + this.wirePose.endPoint.y) / 2;
      const angle = Math.atan2(
        this.wirePose.endPoint.y - this.wirePose.startPoint.y,
        this.wirePose.endPoint.x - this.wirePose.startPoint.x
      ) * (180 / Math.PI);
      
      // 更新姿态
      this.wirePose.position = { x: midX, y: midY };
      this.wirePose.rotation = angle;
      
      // 更新基类位置
      this.wirePose.position = { x: midX, y: midY };
      // this.rotation 不存在， Wire不需要rotation属性
    }
    
    return true;
  }
  
  // 废弃的鼠标事件处理方法已移除，请使用新的被动渲染模式
  // 废弃的鼠标事件处理方法已移除，请使用新的被动渲染模式
  public onMouseDown(position: { x: number; y: number }): boolean {
    const distanceToStart = Math.sqrt(
      Math.pow(position.x - this.wirePose.startPoint.x, 2) + 
      Math.pow(position.y - this.wirePose.startPoint.y, 2)
    );
    const distanceToEnd = Math.sqrt(
      Math.pow(position.x - this.wirePose.endPoint.x, 2) + 
      Math.pow(position.y - this.wirePose.endPoint.y, 2)
    );
    const distanceToMid = Math.sqrt(
      Math.pow(position.x - this.wirePose.position.x, 2) + 
      Math.pow(position.y - this.wirePose.position.y, 2)
    );
    
    const threshold = 15;
    
    if (distanceToStart < threshold) {
      this.wireDragMode = 'start';
    } else if (distanceToEnd < threshold) {
      this.wireDragMode = 'end';
    } else if (distanceToMid < threshold) {
      this.wireDragMode = 'whole';
    }
    
    if (this.wireDragMode !== 'none') {
      this.isDragging = true;
      this.dragStartPos = { ...position };
      this.initialWirePose = { ...this.wirePose };
      return true;
    }
    
    return false;
  }
  
  // 废弃的鼠标释放方法已移除，请使用新的被动渲染模式
  public onMouseUp(): void {
    this.isDragging = false;
    this.wireDragMode = 'none';
    this.initialWirePose = null;
  }
}

// ================== Connection Manager ================== //

/**
 * Pin样式管理器
 */
export class PinStyleManager {
  private static readonly styles: Record<string, PinStyle> = {
    default: {
      radius: 3,
      fill: '#FF6347',
      stroke: '#000000',
      strokeWidth: 1
    },
    hover: {
      radius: 5,
      fill: '#4CAF50',
      stroke: '#2E7D32',
      strokeWidth: 2,
      animation: 'pulse 1s infinite'
    },
    connecting: {
      radius: 6,
      fill: '#2196F3',
      stroke: '#1976D2',
      strokeWidth: 2
    },
    validTarget: {
      radius: 6,
      fill: '#4CAF50',
      stroke: '#2E7D32',
      strokeWidth: 2,
      animation: 'pulse 0.5s infinite'
    },
    invalidTarget: {
      radius: 3,
      fill: '#F44336',
      stroke: '#D32F2F',
      strokeWidth: 2,
      opacity: 0.5
    }
  };

  static getStyle(state: string): PinStyle {
    return this.styles[state] || this.styles.default;
  }

  static applyStyle(element: SVGCircleElement, state: string): void {
    // 移除所有状态类
    element.classList.remove('connecting', 'valid-target', 'invalid-target');
    
    // 添加对应的状态类
    if (state !== 'default' && state !== 'hover') {
      element.classList.add(state);
    }
    
    // 对于default和hover状态，使用CSS内置的:hover伪类
    // 只设置非hover状态的基础属性，让CSS处理hover效果
    if (state !== 'hover') {
      const style = this.getStyle(state);
      element.setAttribute('r', style.radius.toString());
      element.setAttribute('fill', style.fill);
      element.setAttribute('stroke', style.stroke);
      element.setAttribute('stroke-width', style.strokeWidth.toString());
      
      if (style.opacity !== undefined) {
        element.setAttribute('opacity', style.opacity.toString());
      } else {
        element.removeAttribute('opacity');
      }
    }
    // 对于hover状态，不设置任何属性，完全依赖CSS:hover伪类
  }
}

/**
 * 连接验证器
 */
export class ConnectionValidator {
  static validateConnection(sourcePin: IPin, targetPin: IPin): ConnectionValidationResult {
    // 不能连接到自己
    if (sourcePin.componentId === targetPin.componentId) {
      return { isValid: false, reason: '不能连接到同一元件' };
    }
    
    // 检查是否已经是同一个引脚
    if (sourcePin.id === targetPin.id) {
      return { isValid: false, reason: '不能连接到同一个引脚' };
    }
    
    // 检查是否已连接
    if (sourcePin.connectedPins.includes(targetPin)) {
      return { isValid: false, reason: '已经连接到此引脚' };
    }
    
    // 电气类型兼容性检查
    if (!this.isElectricalTypeCompatible(sourcePin, targetPin)) {
      return { isValid: false, reason: '电气类型不兼容' };
    }
    
    return { isValid: true };
  }

  private static isElectricalTypeCompatible(sourcePin: IPin, targetPin: IPin): boolean {
    // 基本兼容性规则
    const incompatiblePairs: Array<[string, string]> = [
      ['Power', 'Power'],
      ['Ground', 'Ground']
    ];
    
    return !incompatiblePairs.some(([type1, type2]) => 
      (sourcePin.electricalType === type1 && targetPin.electricalType === type2) ||
      (sourcePin.electricalType === type2 && targetPin.electricalType === type1)
    );
  }
}

/**
 * 连接管理器实现
 */
export class ConnectionManager implements IConnectionManager {
  private state: ConnectionState = ConnectionState.None;
  private sourcePin: IPin | null = null;
  private connectionLine: SVGLineElement | SVGPathElement | null = null;
  private canvas: SVGSVGElement | null = null;
  private getElementById: ((id: string) => ICircuitElement | undefined) | null = null;
  private validTargets: IPin[] = [];
  private connectionStyle: ConnectionStyle = ConnectionStyle.Straight;
  private createWireCallback: ((sourcePin: IPin, targetPin: IPin) => void) | null = null;

  startConnection(pin: IPin, canvas: SVGSVGElement, getElementById: (id: string) => ICircuitElement | undefined, createWireCallback?: (sourcePin: IPin, targetPin: IPin) => void): void {
    this.state = ConnectionState.Connecting;
    this.sourcePin = pin;
    this.canvas = canvas;
    this.getElementById = getElementById;
    this.createWireCallback = createWireCallback || null;
    
    this.createConnectionLine(pin);
    this.setupGlobalEventListeners();
  }

  updateConnection(x: number, y: number): void {
    if (this.connectionLine && this.state === ConnectionState.Connecting && this.sourcePin && this.canvas && this.getElementById) {
      const element = this.getElementById(this.sourcePin.componentId);
      if (!element) return;
      
      const pinPos = element.getPinPosition(this.sourcePin);
      
      // 使用画布对象坐标系（连接线现在添加到canvasContainer中，与其他元件一致）
      const startPos = {
        x: element.position.x + pinPos.x,
        y: element.position.y + pinPos.y
      };
      
      const endPos = { x, y };
      
      // 检查并更新目标Pin的样式
      this.checkValidTargets(x, y);
      
      // 根据样式更新连线
      if (this.connectionLine.tagName === 'line') {
        // 直线
        (this.connectionLine as SVGLineElement).setAttribute('x2', x.toString());
        (this.connectionLine as SVGLineElement).setAttribute('y2', y.toString());
      } else if (this.connectionLine.tagName === 'path') {
        // 路径（贝塞尔曲线或手绘）
        let newPathData: string;
        
        if (this.connectionStyle === ConnectionStyle.Bezier) {
          // 更新贝塞尔曲线路径
          const distance = Math.sqrt(Math.pow(endPos.x - startPos.x, 2) + Math.pow(endPos.y - startPos.y, 2));
          const curvature = Math.min(distance * 0.3, 50);
          
          const midX = (startPos.x + endPos.x) / 2;
          const midY = (startPos.y + endPos.y) / 2;
          
          const angle = Math.atan2(endPos.y - startPos.y, endPos.x - startPos.x) + Math.PI / 2;
          const controlX = midX + Math.cos(angle) * curvature;
          const controlY = midY + Math.sin(angle) * curvature;
          
          newPathData = `M ${startPos.x} ${startPos.y} Q ${controlX} ${controlY} ${endPos.x} ${endPos.y}`;
        } else {
          // 更新手绘路径
          const distance = Math.sqrt(Math.pow(endPos.x - startPos.x, 2) + Math.pow(endPos.y - startPos.y, 2));
          const segments = Math.max(3, Math.floor(distance / 20));
          
          newPathData = `M ${startPos.x} ${startPos.y}`;
          
          for (let i = 1; i <= segments; i++) {
            const t = i / segments;
            const baseX = startPos.x + (endPos.x - startPos.x) * t;
            const baseY = startPos.y + (endPos.y - startPos.y) * t;
            
            const offsetX = (Math.random() - 0.5) * 3;
            const offsetY = (Math.random() - 0.5) * 3;
            
            const pointX = baseX + offsetX;
            const pointY = baseY + offsetY;
            
            if (i === 1) {
              newPathData += ` L ${pointX} ${pointY}`;
            } else {
              const prevT = (i - 1) / segments;
              const prevX = startPos.x + (endPos.x - startPos.x) * prevT;
              const prevY = startPos.y + (endPos.y - startPos.y) * prevT;
              
              const controlX = (prevX + pointX) / 2;
              const controlY = (prevY + pointY) / 2;
              
              newPathData += ` Q ${controlX} ${controlY} ${pointX} ${pointY}`;
            }
          }
        }
        
        (this.connectionLine as SVGPathElement).setAttribute('d', newPathData);
      }
      
      // 检查鼠标下的有效目标
      this.checkValidTargets(x, y);
    }
  }

  completeConnection(targetPin: IPin): boolean {
    if (!this.sourcePin || this.state !== ConnectionState.Connecting) {
      return false;
    }

    const validation = ConnectionValidator.validateConnection(this.sourcePin, targetPin);
    
    // 临时显示验证结果
    const state = validation.isValid ? 'valid-target' : 'invalid-target';
    this.highlightPin(targetPin, state);
    
    if (!validation.isValid) {
      // 短暂显示错误状态后清理
      setTimeout(() => {
        this.clearPinHighlight(targetPin);
        this.showErrorMessage(validation.reason || '连接失败');
        this.cleanup();
      }, 500);
      return false;
    }

    // 创建连接
    this.createWireConnection(this.sourcePin, targetPin);
    this.showSuccessMessage();
    
    // 清理连接状态
    this.cleanup();
    return true;
  }

  cancelConnection(): void {
    this.cleanup();
  }

  getState(): ConnectionState {
    return this.state;
  }

  getSourcePin(): IPin | null {
    return this.sourcePin;
  }

  setConnectionStyle(style: ConnectionStyle): void {
    this.connectionStyle = style;
  }

  getConnectionStyle(): ConnectionStyle {
    return this.connectionStyle;
  }

  private createConnectionLine(pin: IPin): void {
    if (!this.canvas || !this.getElementById) return;

    const element = this.getElementById(pin.componentId);
    if (!element) return;
    
    const pinPos = element.getPinPosition(pin);
    
    // 使用画布对象坐标系（连接线现在添加到canvasContainer中，与其他元件一致）
    const startPos = {
      x: element.position.x + pinPos.x,
      y: element.position.y + pinPos.y
    };

    // 根据样式创建不同的连线元素
    switch (this.connectionStyle) {
      case ConnectionStyle.Bezier:
        this.connectionLine = this.createBezierPath(startPos, startPos);
        break;
      case ConnectionStyle.Handdrawn:
        this.connectionLine = this.createHanddrawnPath(startPos, startPos);
        break;
      default:
        this.connectionLine = this.createStraightLine(startPos, startPos);
        break;
    }

    // 将连接线添加到canvasContainer中，以保持与其他元素一致的坐标系统
    const canvasContainer = this.canvas.querySelector('g') as SVGGElement;
    if (canvasContainer) {
      canvasContainer.appendChild(this.connectionLine);
    } else {
      // 回退：直接添加到canvas
      this.canvas.appendChild(this.connectionLine);
    }
  }

  private createStraightLine(start: {x: number, y: number}, end: {x: number, y: number}): SVGLineElement {
    const line = document.createElementNS('http://www.w3.org/2000/svg', 'line');
    line.setAttribute('x1', start.x.toString());
    line.setAttribute('y1', start.y.toString());
    line.setAttribute('x2', end.x.toString());
    line.setAttribute('y2', end.y.toString());
    line.setAttribute('stroke', '#007acc');
    line.setAttribute('stroke-width', '2');
    line.setAttribute('stroke-dasharray', '5,3');
    line.setAttribute('opacity', '0.8');
    line.id = 'connection-line';
    line.style.pointerEvents = 'none';
    return line;
  }

  private createBezierPath(start: {x: number, y: number}, end: {x: number, y: number}): SVGPathElement {
    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    
    // 计算控制点，创建自然的贝塞尔曲线
    const distance = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2));
    const curvature = Math.min(distance * 0.3, 50); // 控制曲率
    
    // 根据连线方向确定控制点位置
    const midX = (start.x + end.x) / 2;
    const midY = (start.y + end.y) / 2;
    
    // 垂直于连线方向的偏移
    const angle = Math.atan2(end.y - start.y, end.x - start.x) + Math.PI / 2;
    const controlX = midX + Math.cos(angle) * curvature;
    const controlY = midY + Math.sin(angle) * curvature;
    
    const pathData = `M ${start.x} ${start.y} Q ${controlX} ${controlY} ${end.x} ${end.y}`;
    path.setAttribute('d', pathData);
    path.setAttribute('stroke', '#007acc');
    path.setAttribute('stroke-width', '2');
    path.setAttribute('stroke-dasharray', '5,3');
    path.setAttribute('fill', 'none');
    path.setAttribute('opacity', '0.8');
    path.id = 'connection-line';
    path.style.pointerEvents = 'none';
    return path;
  }

  private createHanddrawnPath(start: {x: number, y: number}, end: {x: number, y: number}): SVGPathElement {
    const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    
    // 创建手绘效果的路径
    const distance = Math.sqrt(Math.pow(end.x - start.x, 2) + Math.pow(end.y - start.y, 2));
    const segments = Math.max(3, Math.floor(distance / 20)); // 分段数
    
    let pathData = `M ${start.x} ${start.y}`;
    
    for (let i = 1; i <= segments; i++) {
      const t = i / segments;
      const baseX = start.x + (end.x - start.x) * t;
      const baseY = start.y + (end.y - start.y) * t;
      
      // 添加轻微的随机偏移模拟手绘效果
      const offsetX = (Math.random() - 0.5) * 3;
      const offsetY = (Math.random() - 0.5) * 3;
      
      const pointX = baseX + offsetX;
      const pointY = baseY + offsetY;
      
      if (i === 1) {
        pathData += ` L ${pointX} ${pointY}`;
      } else {
        // 使用二次贝塞尔曲线连接点，创建更平滑的手绘效果
        const prevT = (i - 1) / segments;
        const prevX = start.x + (end.x - start.x) * prevT;
        const prevY = start.y + (end.y - start.y) * prevT;
        
        const controlX = (prevX + pointX) / 2;
        const controlY = (prevY + pointY) / 2;
        
        pathData += ` Q ${controlX} ${controlY} ${pointX} ${pointY}`;
      }
    }
    
    path.setAttribute('d', pathData);
    path.setAttribute('stroke', '#007acc');
    path.setAttribute('stroke-width', '2.5');
    path.setAttribute('stroke-dasharray', '4,2');
    path.setAttribute('fill', 'none');
    path.setAttribute('opacity', '0.8');
    path.setAttribute('stroke-linecap', 'round');
    path.setAttribute('stroke-linejoin', 'round');
    path.id = 'connection-line';
    path.style.pointerEvents = 'none';
    return path;
  }

  private setupGlobalEventListeners(): void {
    if (!this.canvas) return;

    const handleMouseMove = (e: MouseEvent) => {
      if (!this.canvas) return;
      
      // 使用画布对象坐标转换系统（连接线现在添加到canvasContainer中，与其他元件一致）
      const getScreenToCanvas = (this as any).screenToCanvas;
      let canvasX: number, canvasY: number;
      
      if (getScreenToCanvas) {
        // 使用画布对象坐标转换
        const canvasCoords = getScreenToCanvas(e.clientX, e.clientY);
        canvasX = canvasCoords.x;
        canvasY = canvasCoords.y;
      } else {
        // 回退到直接转换
        const pt = this.canvas.createSVGPoint();
        pt.x = e.clientX;
        pt.y = e.clientY;
        const svgP = pt.matrixTransform(this.canvas.getScreenCTM()?.inverse());
        canvasX = svgP.x;
        canvasY = svgP.y;
      }
      
      this.updateConnection(canvasX, canvasY);
    };

    const handleMouseUp = (e: MouseEvent) => {
      if (!this.canvas) return;
      
      // 使用画布对象坐标转换系统（连接线现在添加到canvasContainer中，与其他元件一致）
      const getScreenToCanvas = (this as any).screenToCanvas;
      let canvasX: number, canvasY: number;
      
      if (getScreenToCanvas) {
        // 使用画布对象坐标转换
        const canvasCoords = getScreenToCanvas(e.clientX, e.clientY);
        canvasX = canvasCoords.x;
        canvasY = canvasCoords.y;
      } else {
        // 回退到直接转换
        const pt = this.canvas.createSVGPoint();
        pt.x = e.clientX;
        pt.y = e.clientY;
        const svgP = pt.matrixTransform(this.canvas.getScreenCTM()?.inverse());
        canvasX = svgP.x;
        canvasY = svgP.y;
      }
      
      // 检查是否在某个Pin上释放
      this.checkValidTargets(canvasX, canvasY);
      const targetPin = this.findPinAtPosition(canvasX, canvasY);
      if (targetPin) {
        this.completeConnection(targetPin);
      } else {
        this.cancelConnection();
      }
      
      // 清理事件监听器
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);
  }

  private checkValidTargets(x: number, y: number): void {
    // 完全禁用实时高亮检测，避免与CSS hover冲突
    // 只在鼠标释放时检查连接有效性
    return;
  }

  private findPinAtPosition(x: number, y: number): IPin | null {
    // 这个方法将在CanvasManager中被重写
    return null;
  }

  private highlightPin(pin: IPin, styleState: string): void {
    const pinElement = document.querySelector(`[data-pin-id="${pin.id}"]`) as SVGCircleElement;
    if (pinElement) {
      PinStyleManager.applyStyle(pinElement, styleState);
    }
  }

  private clearPinHighlight(pin: IPin): void {
    const pinElement = document.querySelector(`[data-pin-id="${pin.id}"]`) as SVGCircleElement;
    if (pinElement) {
      pinElement.classList.remove('valid-target', 'invalid-target');
    }
  }

  private clearTargetHighlights(): void {
    document.querySelectorAll('[data-pin-id]').forEach(element => {
      const pinElement = element as SVGCircleElement;
      // 只移除连接相关的状态类，保留基础样式
      pinElement.classList.remove('connecting', 'valid-target', 'invalid-target');
    });
  }

  private createWireConnection(sourcePin: IPin, targetPin: IPin): void {
    // 统一处理：所有连接都通过回调函数处理，不再区分元件类型
    if (this.createWireCallback) {
      this.createWireCallback(sourcePin, targetPin);
    }
  }
  


  private showSuccessMessage(): void {
    // 创建成功提示
    this.showNotification('连接成功！', 'success');
  }

  private showErrorMessage(message: string): void {
    // 创建错误提示
    this.showNotification(message, 'error');
  }

  private showNotification(message: string, type: 'success' | 'error'): void {
    const notification = document.createElement('div');
    notification.textContent = message;
    notification.style.cssText = `
      position: fixed;
      top: 20px;
      right: 20px;
      padding: 12px 20px;
      border-radius: 4px;
      font-family: Arial, sans-serif;
      font-size: 14px;
      z-index: 10000;
      animation: slideIn 0.3s ease-out;
      ${type === 'success' 
        ? 'background-color: #4CAF50; color: white;' 
        : 'background-color: #F44336; color: white;'
      }
    `;
    
    document.body.appendChild(notification);
    
    setTimeout(() => {
      notification.style.animation = 'slideOut 0.3s ease-out';
      setTimeout(() => {
        document.body.removeChild(notification);
      }, 300);
    }, 2000);
  }

  private cleanup(): void {
    this.state = ConnectionState.None;
    this.sourcePin = null;
    this.canvas = null;
    this.getElementById = null;
    this.validTargets = [];
    
    if (this.connectionLine) {
      this.connectionLine.remove();
      this.connectionLine = null;
    }
    
    this.clearTargetHighlights();
  }
}